<?php
/**
 * Apache security manager script / demonstration.
 * 
 * @package AP5L
 * @subpackage Apache
 * @license http://www.gnu.org/licenses/gpl-3.0.html GPLv3
 * @copyright 2007, Alan Langford
 * @version $Id: manage.php 91 2009-08-21 02:45:29Z alan.langford@abivia.com $
 * @author Alan Langford <alan.langford@abivia.com>
 */

//
//  Commands in 'cmd'; append '_u' on form/link submit:
//      <null>  Show menu
//      ag      Add group
//      au      Add user
//      aug     Add user to group
//      dg      Delete group
//      du      Delete user
//      dug     Delete user from group
//      lg      List groups
//      lgu     List group's users
//      lu      List users
//      lug     List user's groups
//      scm     Show command menu
//      sp      Set (self) password
//      sup     Set user password
//
// Users in the group <xxx>_mgt can create and manage users and groups with the prefix <xxx>_.
// Users in the "super management" group can do anything.
// If the user hasn't presented authentication credentials, then nothing happens.
//
require_once('http/SecureRedirect.php');

$r = new SecureRedirect();
$r -> redirect('https');

echo '<' . '?xml version="1.0" encoding="utf-8" ?' . '>' . chr(10);
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' . chr(10);
echo ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">' . chr(10);

?>

 
<html>
<head>
<title>Apache Security Manager</title>
</head>
<body>
<?php

function checkPassword($pass1, $pass2) {
    global $msg;
    //
    // Apply password policy here
    //
    if ($pass1 != $pass2) {
        $msg = 'Failure: Passwords do not match.';
    } else if (strlen($pass1) < 6) {
        $msg = 'Failure: Password less than 6 characters long.';
    } else {
        return true;
    }
    return false;
}

function genMenu($pre, $post) {
    $preLink = $pre . '<a href="manage.php?cmd=';
    echo $preLink . 'scm">Menu</a>' . $post;
    echo $preLink . 'lu">List Users</a>' . $post;
    echo $preLink . 'lg">List Groups</a>' . $post;
}

function loadContext() {
    global $loginUser;
    global $manageGroups;
    global $managePrefix;
    global $manageUsers;
    global $superGroup;
    global $superUser;
    global $userInfo;
    
    $userInfo -> loadUsers();
    $userInfo -> loadGroups();
    
    $superUser = $userInfo -> isUserInGroup($loginUser, $superGroup);
    $managePrefix = array();
    if (($groups = $userInfo -> getGroups($loginUser)) !== false) {
        foreach ($groups as $group) {
            if (substr($group, -4) == '_mgt') {
                $managePrefix[] = substr($group, 0, strlen($group) - 3);
            }
        }
    }
    if ($superUser) {
        $manageGroups = $userInfo -> getGroups();
    } else {
        $manageGroups = array();
        foreach ($userInfo -> getGroups() as $group) {
            foreach ($managePrefix as $manage) {
                if ($manage == substr($group, 0, strlen($manage))) {
                    $manageGroups[] = $group;
                }
            }
        }
    }
    
    if ($superUser) {
        $manageUsers = $userInfo -> getUsers();
    } else {
        $manageUsers = array();
        foreach ($userInfo -> getUsers() as $user) {
            foreach ($managePrefix as $manage) {
                if ($manage == substr($user, 0, strlen($manage))) {
                    $manageUsers[] = $user;
                }
            }
        }
    }
}

function setPassword($user, $pass1, $pass2) {
    global $msg;
    global $userInfo;
    
    if (! checkPassword($pass1, $pass2)) {
        return false;
    }
    if ($userInfo -> setApachePassword($user, $pass1)) {
        $msg = 'Success: Password changed for ' . $user . '.<br/>';
        if ($user == $_SERVER['PHP_AUTH_USER']) {
            $msg .= 'You will need to reauthenticate on the next protected request<br/>';
        }
        return true;
    } else {
        $msg = $userInfo -> errMsg;
    }
    return false;
}

$superGroup = 'abivia_mgt';

$loginUser = $_SERVER['PHP_AUTH_USER'];
if (! $loginUser) {
    echo 'Security violation.<br>';
    exit;
}

require_once('apache/ApacheUserAuth.php');

//
// Open the object and get the current users / groups
//
$userInfo = new ApacheUserAuth();
$userInfo -> setPath('/var/www/globalaccess/');
//$userInfo -> setPasswordFile('passwords2');       // Override default for testing

$userInfo -> loadUsers();
$userInfo -> loadGroups();

$superUser = $userInfo -> isUserInGroup($loginUser, $superGroup);

$layout = 'scm';
if (isset($_REQUEST['cmd'])) {
    $cmd = $_REQUEST['cmd'];
} else {
    $cmd = 'scm';
}

$msg = '';
switch ($cmd) {
    case 'ag_u' : {                     // Add group
        $layout = 'lg';
        if (isset($_REQUEST['apfx'])) {
            $prefix = $_REQUEST['apfx'];
        } else {
            $prefix = '';
        }
        if (! $userInfo -> addGroup($prefix . $_REQUEST['agrp'], array())) {
            $msg = $userInfo -> errMsg;
        }
    } break;
    
    case 'au_u' : {                     // Add user
        $layout = 'lu';
        if (isset($_REQUEST['apfx'])) {
            $prefix = $_REQUEST['apfx'];
        } else {
            $prefix = '';
        }
        if (checkPassword($_REQUEST['npwd'], $_REQUEST['npwd2'])) {
            if (! $userInfo -> addUser($prefix . $_REQUEST['ausr'], $_REQUEST['npwd'])) {
                $msg = $userInfo -> errMsg;
            }
        }
    } break;
    
    case 'aug_u' : {                    // Add user to group
        if ($_REQUEST['fc'] == 'lug') {
            if (! $userInfo -> addUserToGroup($_REQUEST['agrp'], $_REQUEST['u'])) {
                $msg = $userInfo -> errMsg;
            }
        } else if ($_REQUEST['fc'] == 'lgu') {
            if (! $userInfo -> addUserToGroup($_REQUEST['g'], $_REQUEST['ausr'])) {
                $msg = $userInfo -> errMsg;
            }
        }   
        $layout = $_REQUEST['fc'];
    } break;
    
    case 'dg' : {                       // Delete group
        if ($_REQUEST['g'] == $superGroup) {
            $msg = 'That, you\'re going to have to do manually!';
        } else if (! $userInfo -> deleteGroup($_REQUEST['g'])) {
            $msg = $userInfo -> errMsg;
        }
        $layout = 'lg';
    } break;
    
    case 'du' : {                       // Delete user
        if ($loginUser == $_REQUEST['u']) {
            $msg = 'you can\'t delete yourself!';
        } else if (! $userInfo -> deleteUser($_REQUEST['u'])) {
            $msg = $userInfo -> errMsg;
        }
        $layout = 'lu';
    } break;
    
    case 'dug' : {                      // Delete user from group
        if (! $userInfo -> deleteUserFromGroup($_REQUEST['g'], $_REQUEST['u'])) {
            $msg = $userInfo -> errMsg;
        }
        $layout = $_REQUEST['fc'];
    } break;
    
    case 'sp_u': {                      // Set self password command
        if (isset($_POST['npwd']) && isset($_POST['npwd2'])) {
            if (! setPassword($loginUser, $_POST['npwd'], $_POST['npwd2'])) {
                $layout = 'sp';
            }
        }
    } break;
    
    case 'sup_u': {                     // Set password command
        $layout = 'lu';
        if (isset($_POST['u']) && isset($_POST['npwd']) && isset($_POST['npwd2'])) {
            if (! setPassword($_POST['u'], $_POST['npwd'], $_POST['npwd2'])) {
                $layout = 'sup';
            }
        }
    } break;
    
    default: {
        $layout = $cmd;
    }
}

loadContext();
if ((! $superUser) && (! count($managePrefix))) {
    //
    // Alas, this lowly user can only change their password...
    //
    $layout = 'sp';
}

switch ($layout) {
    case 'lg': {                        // List groups
        $tableCols = 3;
        $iconCols = $tableCols - 1;
        echo '<form action="manage.php" method="post">';
        echo '<input name="cmd" type="hidden" value="ag_u" />';
        echo '<table>';
        echo '<tr><td colspan="' . $tableCols . '">';
        genMenu('', '&nbsp;');
        echo '</td></tr>';
        if ($msg) {
            echo '<tr><td colspan="' . $tableCols . '">' . $msg . '</td></tr>';
        }
        echo '<tr><td>Group</td><td>Users</td><td>Delete</td></tr>';
        $icon = '<img src="icon.gif" border="0" height="16" width="16" title="';
        foreach ($manageGroups as $group) {
            $preLink = '</td><td><a href="manage.php?g=' . urlencode($group) . '&amp;cmd=';
            echo '<tr><td>' . $group . $preLink . 'lgu">' . $icon . 'List Users" /></a>';
            if ((substr($group, -4) == '_mgt') && ! $superUser) {
                echo '</td><td>&nbsp;';
            } else {
                echo $preLink . 'dg">' . $icon . 'Delete Group" /></a>';
            }
            echo '</td></tr>';
        }
        if ($superUser || count($managePrefix)) {
            echo '<tr><td colspan="' . $tableCols . '">Add New Group</td></tr>';
            echo '<tr><td>Group Name</td><td colspan="' . $iconCols . '">';
            if (count($managePrefix)) {
                echo '<select name="apfx">';
                if ($superUser) {
                    echo '<option value="">No Prefix</option>';
                }
                foreach ($managePrefix as $prefix) {
                    echo '<option value="' . $prefix  . '">' . $prefix  . '</option>';
                }
                echo '</select>';
            }
            echo '<input type="text" name="agrp" size="50" maxlength="255" /></td></tr>';
            echo '<tr><td>&nbsp;</td><td colspan="' . $iconCols . '">';
            echo '<input type="submit" name="add" value="Add" /></td></tr>';
        }
        echo '</table>';
        echo '</form>';
    } break;
    
    case 'lgu': {                       // List group's users
        echo '<form action="manage.php" method="post">';
        echo '<input name="cmd" type="hidden" value="aug_u" />';
        echo '<input name="fc" type="hidden" value="lgu" />';
        echo '<input name="g" type="hidden" value="' . $_REQUEST['g'] . '" />';
        $groupUsers = array_intersect($manageUsers, $userInfo -> getUsers($_REQUEST['g']));
        echo '<table>';
        echo '<tr><td colspan="2">';
        genMenu('', '&nbsp;');
        echo '</td></tr>';
        if ($msg) {
            echo '<tr><td colspan="3">' . $msg . '</td></tr>';
        }
        echo '<tr><td>Group</td><td>' . $_REQUEST['g'] . '</td></tr>';
        if (count($groupUsers)) {
            echo '<tr><td>User</td><td>Delete</td></tr>';
            $preLink = '</td><td><a href="manage.php?g=' . urlencode($_REQUEST['g'])
                . '&amp;cmd=dug&amp;fc=lgu&amp;u=';
            foreach ($groupUsers as $user) {
                echo '<tr><td>' . $user . $preLink . $user . '">Remove</a></td></tr>';
            }
        } else {
            echo '<tr><td colspan="2">Group has no users.</td></tr>';
        }
        $groupUsers = array_diff($manageUsers, $userInfo -> getUsers($_REQUEST['g']));
        if (count($groupUsers)) {
            echo '<tr><td>Add User</td><td><select name="ausr">';
            foreach ($groupUsers as $user) {
                echo '<option value="' . $user  . '">' . $user  . '</option>';
            }
            echo '</select><input type="submit" name="add" value="Add" /></td></tr>';
        }
        echo '</table>';
        echo '</form>';
    } break;
    
    case 'lu': {                        // List users
        $tableCols = 4;
        $iconCols = $tableCols - 1;
        echo '<form action="manage.php" method="post">';
        echo '<input name="cmd" type="hidden" value="au_u" />';
        echo '<table>';
        echo '<tr><td colspan="' . $tableCols . '">';
        genMenu('', '&nbsp;');
        echo '</td></tr>';
        if ($msg) {
            echo '<tr><td colspan="' . $tableCols . '">' . $msg . '</td></tr>';
        }
        echo '<tr><td>User</td><td>Pass</td><td>Groups</td><td>Delete</td></tr>';
        $icon = '<img src="icon.gif" border="0" height="16" width="16" title="';
        foreach ($manageUsers as $user) {
            $preLink = '</td><td><a href="manage.php?u=' . urlencode($user) . '&amp;cmd=';
            echo '<tr><td>' . $user . $preLink . 'sup">' . $icon . 'Change Password" /></a>';
            echo $preLink . 'lug">' . $icon . 'List User\'s Groups" /></a>';
            if ($user == $loginUser) {
                echo '</td><td>&nbsp;';
            } else {
                echo $preLink . 'du">' . $icon . 'Delete User" /></a>';
            }
            echo '</td></tr>';
        }
        if ($superUser || count($managePrefix)) {
            echo '<tr><td colspan="' . $tableCols . '">Add New User</td></tr>';
            echo '<tr><td>User Name</td><td colspan="' . $iconCols . '">';
            if (count($managePrefix)) {
                echo '<select name="apfx">';
                if ($superUser) {
                    echo '<option value="">No Prefix</option>';
                }
                foreach ($managePrefix as $prefix) {
                    echo '<option value="' . $prefix  . '">' . $prefix  . '</option>';
                }
                echo '</select>';
            }
            echo '<input type="text" name="ausr" size="50" maxlength="255" /></td></tr>';
            echo '<tr><td>Password</td>';
            echo '<td colspan="' . $iconCols . '">';
            echo '<input name="npwd" type="password" size="50" maxlength="255" /></td></tr>';
            echo '<tr><td>Repeat Password</td>';
            echo '<td colspan="' . $iconCols . '">';
            echo '<input name="npwd2" type="password" size="50" maxlength="255" /></td></tr>';
            echo '<tr><td>&nbsp;</td><td colspan="' . $iconCols . '">';
            echo '<input type="submit" name="add" value="Add" /></td></tr>';
        }
        echo '</table>';
        echo '</form>';
    } break;
    
    case 'lug': {                       // List user's groups
        echo '<form action="manage.php" method="post">';
        echo '<input name="cmd" type="hidden" value="aug_u" />';
        echo '<input name="fc" type="hidden" value="lug" />';
        echo '<input name="u" type="hidden" value="' . $_REQUEST['u'] . '" />';
        $userGroups = array_intersect($manageGroups, $userInfo -> getGroups($_REQUEST['u']));
        echo '<table>';
        echo '<tr><td colspan="2">';
        genMenu('', '&nbsp;');
        echo '</td></tr>';
        if ($msg) {
            echo '<tr><td colspan="3">' . $msg . '</td></tr>';
        }
        echo '<tr><td>User</td><td>' . $_REQUEST['u'] . '</td></tr>';
        if (count($userGroups)) {
            echo '<tr><td>Group</td><td>Delete</td></tr>';
            $preLink = '</td><td><a href="manage.php?u=' . urlencode($_REQUEST['u'])
                . '&amp;cmd=dug&amp;fc=lug&amp;g=';
            foreach ($userGroups as $group) {
                echo '<tr><td>' . $group;
                if ($group == $superGroup) {
                    echo '</td><td>Locked</td></tr>';
                } else {
                    echo $preLink . $group . '">Remove</a></td></tr>';
                }
            }
        } else {
            echo '<tr><td colspan="2">User is not in any group.</td></tr>';
        }
        $userGroups = array_diff($manageGroups, $userInfo -> getGroups($_REQUEST['u']));
        if (count($userGroups)) {
            echo '<tr><td>Add to Group</td><td><select name="agrp">';
            foreach ($userGroups as $group) {
                echo '<option value="' . $group  . '">' . $group  . '</option>';
            }
            echo '</select><input type="submit" name="add" value="Add" /></td></tr>';
        }
        echo '</table>';
        echo '</form>';
    } break;
    
    case 'scm': {
        echo '<table>';
        if ($msg) {
            echo '<tr><td>' . $msg . '</td></tr>';
        }
        echo '<tr><td>Commands</td></tr>';
        genMenu('<tr><td>','</td></tr>');
        echo '</table>';
    } break;
    
    case 'sp': {
        echo '<form action="manage.php" method="post">';
        echo '<input name="cmd" type="hidden" value="sp_u" />';
        echo '<table>';
        echo '<tr><td colspan="2">Set Password</td></tr>';
        if ($msg) {
            echo '<tr><td colspan="2">' . $msg . '</td></tr>';
        }
        echo '<tr><td>New Access Pass</td>';
        echo '<td><input name="npwd" type="password" size="50" maxlength="255" /></td></tr>';
        echo '<tr><td>Repeat Password</td>';
        echo '<td><input name="npwd2" type="password" size="50" maxlength="255" /></td></tr>';
        echo '<tr><td colspan="2">Passwords must be at least 6 characters in length.</td></tr>';
        echo '<tr><td>&nbsp;</td><td><input name="go" type="submit" /></td></tr>';
        echo '</table>';
        echo '</form>';
    } break;
    
    case 'sup': {
        echo '<form action="manage.php" method="post">';
        echo '<input name="cmd" type="hidden" value="sup_u" />';
        echo '<input name="u" type="hidden" value="' . $_REQUEST['u'] . '" />';
        echo '<table>';
        echo '<tr><td colspan="2">Set Password</td></tr>';
        if ($msg) {
            echo '<tr><td colspan="2">' . $msg . '</td></tr>';
        }
        echo '<tr><td>User</td><td>' . $_REQUEST['u'] . '</td></tr>';
        echo '<tr><td>New Access Pass</td>';
        echo '<td><input name="npwd" type="password" size="50" maxlength="255" /></td></tr>';
        echo '<tr><td>Repeat Password</td>';
        echo '<td><input name="npwd2" type="password" size="50" maxlength="255" /></td></tr>';
        echo '<tr><td colspan="2">Passwords must be at least 6 characters in length.</td></tr>';
        echo '<tr><td>&nbsp;</td><td><input name="go" type="submit" /></td></tr>';
        echo '</table>';
        echo '</form>';
    } break;
    
    default: {
        echo $msg . '<br/>Unknown layout ' . $layout . '<br/>';
    } break;
}

?>
</body>
</html>